<!DOCTYPE html>
<html lang=zh-CN>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta property="og:description" content="samuel-24276的博客">
    <meta property="og:type" content="website">
    <meta name="description" content="samuel-24276的博客">
    <meta name="keyword"  content="aircloud">
    <link rel="shortcut icon" href="/myblog/img/favicon.ico">

    <title>
        
        C++14 for Qt programmers - samuel-24276的博客 | samuel-24276&#39;s Blog
        
    </title>

    <!-- Custom CSS -->
    
<link rel="stylesheet" href="/myblog/css/aircloud.css">

    
<link rel="stylesheet" href="/myblog/css/gitment.css">

    <!--<link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css">-->
    <link href="//at.alicdn.com/t/font_620856_28hi1hpxx24.css" rel="stylesheet" type="text/css">
    <!-- ga & ba script hoook -->
    <script></script>
<meta name="generator" content="Hexo 7.1.1"></head>

<body>

<div class="site-nav-toggle" id="site-nav-toggle">
    <button>
        <span class="btn-bar"></span>
        <span class="btn-bar"></span>
        <span class="btn-bar"></span>
    </button>
</div>

<div class="index-about">
    <i> Like what you do, do what you like </i>
</div>

<div class="index-container">
    
    <div class="index-left">
        
<div class="nav" id="nav">
    <div class="avatar-name">
        <div class="avatar ">
            <img src="/myblog/img/avatar.jpg" />
        </div>
        <div class="name">
            <i>samuel-24276</i>
        </div>
    </div>
    <div class="contents" id="nav-content">
        <ul>
            <li >
                <a href="/myblog/">
                    <i class="iconfont icon-shouye1"></i>
                    <span>主页</span>
                </a>
            </li>
            <li >
                <a href="/myblog/tags">
                    <i class="iconfont icon-biaoqian1"></i>
                    <span>标签</span>
                </a>
            </li>
            <li >
                <a href="/myblog/archives">
                    <i class="iconfont icon-guidang2"></i>
                    <span>存档</span>
                </a>
            </li>
            <li >
                <a href="/myblog/collect/">
                    <i class="iconfont icon-shoucang1"></i>
                    <span>收藏</span>
                </a>
            </li>
            <li >
                <a href="/myblog/about/">
                    <i class="iconfont icon-guanyu2"></i>
                    <span>关于</span>
                </a>
            </li>
            
            <li>
                <a id="search">
                    <i class="iconfont icon-sousuo1"></i>
                    <span>搜索</span>
                </a>
            </li>
            
        </ul>
    </div>
    
        <div id="toc" class="toc-article">
    <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Generic-lambda"><span class="toc-text">Generic lambda</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Relaxed-Constant-expressions"><span class="toc-text">Relaxed Constant expressions</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Small-features"><span class="toc-text">Small features</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#Group-Separators-in-Numbers"><span class="toc-text">Group Separators in Numbers</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Binary-literal"><span class="toc-text">Binary literal</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Automatic-return-type-detection"><span class="toc-text">Automatic return type detection</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Variable-template"><span class="toc-text">Variable template</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Uniform-initialization-of-structures-with-non-static-data-member-initializers"><span class="toc-text">Uniform initialization of structures with non static data member initializers</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Reference-Qualifiers%E5%BC%95%E7%94%A8%E9%99%90%E5%AE%9A%E7%AC%A6"><span class="toc-text">Reference Qualifiers引用限定符</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Changes-in-the-standard-library"><span class="toc-text">Changes in the standard library.</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Conclusion"><span class="toc-text">Conclusion</span></a></li></ol>
</div>
    
</div>


<div class="search-field" id="search-field">
    <div class="search-bg" id="search-bg"></div>
    <div class="search-container">
        <div class="search-input">
            <span id="esc-search"> <i class="icon-fanhui iconfont"></i></span>
            <input id="search-input"/>
            <span id="begin-search">搜索</span>
        </div>
        <div class="search-result-container" id="search-result-container">

        </div>
    </div>
</div>

        <div class="index-about-mobile">
            <i> Like what you do, do what you like </i>
        </div>
    </div>
    
    <div class="index-middle">
        <!-- Main Content -->
        


<div class="post-container">
    <div class="post-title">
        C++14 for Qt programmers
    </div>

    <div class="post-meta">
        <span class="attr">发布于：<span>2021-05-16 13:55:29</span></span>
        
        <span class="attr">标签：/
        
        <a class="tag" href="/myblog/tags/#Qt" title="Qt">Qt</a>
        <span>/</span>
        
        <a class="tag" href="/myblog/tags/#C++" title="C++">C++</a>
        <span>/</span>
        
        <a class="tag" href="/myblog/tags/#文章翻译" title="文章翻译">文章翻译</a>
        <span>/</span>
        
        
        </span>
        <span class="attr">访问：<span id="busuanzi_value_page_pv"></span>
</span>
</span>
    </div>
    <div class="post-content no-indent">
        <blockquote>
<p>文章来源：<a target="_blank" rel="noopener" href="https://woboq.com/blog/cpp14-in-qt.html">C++14 for Qt programmers</a></p>
</blockquote>
<p>c++ 14是今年将发布的标准版本的名称。c++ 11带来了更多编译器需要时间才能实现的特性，而c++ 14的变化要轻得多，已经由clang或gcc等编译器实现了。</p>
<p>Qt 5已经在许多方面进行了改编，因此您可以利用c++ 11的新特性。你可以在我之前的文章<a target="_blank" rel="noopener" href="https://woboq.com/blog/cpp11-in-qt5.html">C++11 in Qt5 (woboq.com)</a>中读到。这篇文章提到了c++ 14中的一些变化以及对Qt用户的影响。</p>
<h1 id="Generic-lambda"><a href="#Generic-lambda" class="headerlink" title="Generic lambda"></a>Generic lambda</h1><p>c++ 11引入了lambda函数，Qt5允许您使用新的连接语法将信号连接到它们。c++ 14简化了lambda函数的使用，因为参数可以自动推导。您可以使用auto作为参数类型，而不是显式地编写类型。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">connect</span>(sender, &amp;Sender::valueChanged, [=](<span class="type">const</span> <span class="keyword">auto</span> &amp;newValue) &#123;</span><br><span class="line">       receiver-&gt;<span class="built_in">updateValue</span>(<span class="string">&quot;senderValue&quot;</span>, newValue);</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure>

<p>在内部，lambda函数只是一个带有操作符()的函子对象。对于泛型lamdba，该操作符现在是一个模板化函数。我不得不做一个改变，包括在Qt 5.1已经支持这样的函子。</p>
<p>c++ 14还增加了在捕获中包含表达式的可能性。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">connect</span>(sender, &amp;Sender::valueChanged, [reciever=<span class="built_in">getReciever</span>()](<span class="type">const</span> <span class="keyword">auto</span> &amp;newValue) &#123;</span><br><span class="line">       receiver-&gt;<span class="built_in">updateValue</span>(<span class="string">&quot;senderValue&quot;</span>, newValue);</span><br><span class="line">   &#125;);</span><br></pre></td></tr></table></figure>

<h1 id="Relaxed-Constant-expressions"><a href="#Relaxed-Constant-expressions" class="headerlink" title="Relaxed Constant expressions"></a>Relaxed Constant expressions</h1><p>c++ 11加入了新的constexpr关键字。Qt 4.8添加了一个新的宏Q_DECL_CONSTEXPR，在支持的情况下扩展为constexpr，在Qt 5中，我们已经在许多函数中使用了这个宏。</p>
<p>c++ 14放宽了constexpr中允许的内容的规则。c++ 11规则只允许一个return语句，并且只能应用于const函数。c++ 14允许在编译时计算几乎任何代码。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* This function was not valid in C++11 because it is composed of several statements,</span></span><br><span class="line"><span class="comment"> * it has a loop, and a local variable. It is now allowed in C++14 */</span></span><br><span class="line"><span class="function"><span class="keyword">constexpr</span> <span class="type">int</span> <span class="title">myFunction</span><span class="params">(<span class="type">int</span> v)</span> </span>&#123;</span><br><span class="line">  <span class="type">int</span> x = <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">while</span> (x &lt; v*v)</span><br><span class="line">    x*=<span class="number">2</span>;</span><br><span class="line">  <span class="keyword">return</span> x;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在c++ 11中声明为constexpr的成员函数被自动视为const。这种情况不再存在，因为非const函数也可以是constexpr。<br>此更改的结果是，未显式标记为const的constexpr成员函数将在c++ 14中改变const-ness，这是一个二进制不兼容的更改。幸运的是，在Qt中，所有Q_DECL_CONSTEXPR成员函数都显式声明为const，以保持与非c++ 11代码的二进制兼容性。</p>
<p>现在我们可以开始注释(annotating )非const函数了，比如很多类的operator&#x3D;。因此，Qt 5.5将附带一个新的宏Q_DECL_RELAXED_CONSTEXPR，当编译器处于c++ 14模式时，它将扩展为constexpr。然后，我们将能够开始使用Q_DECL_RELAXED_CONSTEXPR注释相关函数</p>
<h1 id="Small-features"><a href="#Small-features" class="headerlink" title="Small features"></a>Small features</h1><p>c++ 14还附带了很多方便的小特性。这对Qt没有直接影响，但如果你启用c++ 14，就可以在你的程序中使用。我们只是确保像moc这样的工具能够处理它们。</p>
<h2 id="Group-Separators-in-Numbers"><a href="#Group-Separators-in-Numbers" class="headerlink" title="Group Separators in Numbers"></a>Group Separators in Numbers</h2><p>如果你在你的代码中写了一个巨大的常量，你现在可以使用’作为组分隔符:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> i = <span class="number">123&#x27;456&#x27;789</span>;</span><br></pre></td></tr></table></figure>

<h2 id="Binary-literal"><a href="#Binary-literal" class="headerlink" title="Binary literal"></a>Binary literal</h2><p>在c++中，你可以用十进制、八进制(从0开始)、十六进制(从0x开始)来写你的数字。现在还可以使用0b前缀写入二进制。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> i = <span class="number">0b0001&#x27;0000&#x27;0001</span>;</span><br></pre></td></tr></table></figure>

<h2 id="Automatic-return-type-detection"><a href="#Automatic-return-type-detection" class="headerlink" title="Automatic return type detection"></a>Automatic return type detection</h2><p>如果你有一个内联函数，你可以使用auto作为返回类型，你不再需要指定它。编译器会为你推导它</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// return type auto detected to be &#x27;int&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">auto</span> <span class="title">sum</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span>&#123; <span class="keyword">return</span> a+b; &#125;</span><br></pre></td></tr></table></figure>

<p>然而，对于slot或可调用方法，这是不支持的，因为moc将无法检测返回类型</p>
<h2 id="Variable-template"><a href="#Variable-template" class="headerlink" title="Variable template"></a>Variable template</h2><p>你可以有函数模板或类模板。现在你也可以有变量模板。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt; <span class="type">const</span> T pi = <span class="number">3.141592653589793</span>;</span><br><span class="line"><span class="comment">/*...*/</span></span><br><span class="line">    <span class="type">float</span> f = pi&lt;<span class="type">float</span>&gt;;</span><br><span class="line">    <span class="type">double</span> d = pi&lt;<span class="type">double</span>&gt;;</span><br></pre></td></tr></table></figure>

<h2 id="Uniform-initialization-of-structures-with-non-static-data-member-initializers"><a href="#Uniform-initialization-of-structures-with-non-static-data-member-initializers" class="headerlink" title="Uniform initialization of structures with non static data member initializers"></a>Uniform initialization of structures with non static data member initializers</h2><p>使用非静态数据成员初始化器对结构进行统一初始化</p>
<p>在c++ 11中，可以使用统一初始化来初始化一个没有构造函数的结构体，方法是初始化所有成员。c++ 11还增加了在类声明中直接使用内联非静态数据成员初始化器的可能性。但是你不能同时使用这两者。在c++ 14中，你可以。这段代码工作，并做你所期望的:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">MyStruct</span> &#123;</span><br><span class="line">    <span class="type">int</span> x;</span><br><span class="line">    QString str;</span><br><span class="line">    <span class="type">bool</span> flag = <span class="literal">false</span>;</span><br><span class="line">    QByteArray str2 = <span class="string">&quot;something&quot;</span>;</span><br><span class="line">&#125;;</span><br><span class="line"> </span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"><span class="comment">// did not compile in C++11 because MyStruct was not an &quot;aggregate&quot;</span></span><br><span class="line">MyStruct s = &#123; <span class="number">12</span>, <span class="string">&quot;1234&quot;</span>, <span class="literal">true</span> &#125;;</span><br><span class="line"><span class="built_in">Q_ASSERT</span>(s.str2 == <span class="string">&quot;something&quot;</span>);</span><br></pre></td></tr></table></figure>

<h1 id="Reference-Qualifiers引用限定符"><a href="#Reference-Qualifiers引用限定符" class="headerlink" title="Reference Qualifiers引用限定符"></a>Reference Qualifiers引用限定符</h1><p>这不是c++ 14的特性，而是c++ 11的变化。但我们只是在Qt5周期的后期才开始使用它，我在之前的博客文章中没有提到它，所以我在这里提到它。</p>
<p>考虑下面的代码:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">QString lower = QString::<span class="built_in">fromUtf8</span>(data).<span class="built_in">toLower</span>();</span><br></pre></td></tr></table></figure>

<p>fromUtf8返回一个临时对象。如果toLower可以重用由字符串分配的内存并在适当的地方进行转换，那就太好了。这就是成员函数的引用限定符的作用。</p>
<p>(代码从qstring.h简化:)</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">QString</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="comment">/* ... */</span></span><br><span class="line"> </span><br><span class="line">    <span class="function">QString <span class="title">toLower</span><span class="params">()</span> <span class="type">const</span> &amp;</span></span><br><span class="line"><span class="function">    </span>&#123; <span class="comment">/* ... returns a copy with lower case character ... */</span> &#125;</span><br><span class="line">    <span class="function">QString <span class="title">toLower</span><span class="params">()</span> &amp;&amp;</span></span><br><span class="line"><span class="function">    </span>&#123; <span class="comment">/* ... do the conversion in-place ... */</span> &#125;</span><br><span class="line">     </span><br><span class="line">    <span class="comment">/* ... */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>注意toLower末尾的&amp;和&amp;&amp;。它们是引用限定符，根据this指针的引用类型重载函数，就像const限定符重载this的constness一样。当对一个临时(右值引用)调用toLower时，第二个重载(带有&amp;&amp;的重载)将被选择，转换将在适当的位置完成。</p>
<p>The functions that benefit from the optimisation in Qt 5.4 are: <code>QString::toUpper, QString::toLower, QString::toCaseFolded, QString::toLatin1, QString::toLocal8Bit, QString::toUtf8, QByteArray::toUpper, QByteArray::toLower, QImage::convertToFormat, QImage::mirorred, QImage::rgbSwapped, QVersionNumber::normalized, QVersionNumber::segment</code></p>
<h1 id="Changes-in-the-standard-library"><a href="#Changes-in-the-standard-library" class="headerlink" title="Changes in the standard library."></a>Changes in the standard library.</h1><p>c++ 11和c++ 14在标准库中添加了许多特性，与QtCore的许多特性竞争。然而，Qt很少使用标准库。特别是，我们不希望将标准库作为ABI的一部分。这将允许即使在标准库更改时也保持二进制兼容性(例如libstdc++ vs. libcpp)。此外，Qt仍然支持没有c++ 11标准库的旧平台。这确实限制了我们的使用。</p>
<p>然而，Qt5已经弃用了它自己的算法库，现在建议使用来自STL的算法(例如，std::sort而不是qSort)。</p>
<h1 id="Conclusion"><a href="#Conclusion" class="headerlink" title="Conclusion"></a>Conclusion</h1><p>在您的项目中使用这些特性可能还需要一些时间。但我希望，到目前为止，您已经开始像许多其他项目(Qt Creator, KDE, LLVM)那样使用c++ 11特性了。</p>
<p>MSVC将在默认情况下使用新的编译器启用c++ 14，但clang和gcc需要一个特殊的编译标志(目前是-std&#x3D;c++1y)。使用qmake，你可以让你的项目从Qt 5.4开始使用c++ 14构建:</p>
<p>CONFIG +&#x3D; c++14</p>
<hr>

        
            <div class="donate-container">
    <div class="donate-button">
        <button id="donate-button">赞赏</button>
    </div>
    <div class="donate-img-container hide" id="donate-img-container">
        <img id="donate-img" src="" data-src="/myblog/img/donate.jpg">
        <p> 感谢鼓励 </p>
    </div>
</div>
        
        <br />
        <div id="comment-container">
        </div>
        <div id="disqus_thread"></div>
        <div id="lv-container"></div>
        <div class="giscus"></div>
    </div>
</div>

    </div>
</div>


<footer class="footer">
    <ul class="list-inline text-center">
        
        

        

        

        
        <li>
            <a target="_blank"  href="https://github.com/samuel-24276">
                            <span class="fa-stack fa-lg">
                                <i class="iconfont icon-github"></i>
                            </span>
            </a>
        </li>
        

        

    </ul>
    
    <p>
        <span>/</span>
        
        <span><a target="_blank" rel="noopener" href="https://github.com/samuel-24276">samuel-24276&#39;s Page</a></span>
        <span>/</span>
        
        <span><a target="_blank" rel="noopener" href="https://beian.miit.gov.cn/">北京-未备案</a></span>
        <span>/</span>
        
        <span><a href="#">返回顶部</a></span>
        <span>/</span>
        
    </p>
    
    <p>
        <span id="busuanzi_container_site_pv">
            <span id="busuanzi_value_site_pv"></span>PV
        </span>
        <span id="busuanzi_container_site_uv">
            <span id="busuanzi_value_site_uv"></span>UV
        </span>
        Created By <a target="_blank" rel="noopener" href="https://hexo.io/">Hexo</a>  Theme <a target="_blank" rel="noopener" href="https://github.com/aircloud/hexo-theme-aircloud">AirCloud</a></p>
</footer>




</body>

<script>
    // We expose some of the variables needed by the front end
    window.hexo_search_path = "search.json"
    window.hexo_root = "/myblog/"
    window.isPost = true
</script>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

<script src="/myblog/js/index.js"></script>

<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>






    <script type="text/javascript">
       (function() {
           if (typeof LivereTower === 'function') { return; }

           var j, d = document.getElementById('lv-container');

           d.setAttribute('data-id','city');
           d.setAttribute('data-uid' , 'MTAyMC80OTA5OC8yNTU5Mw==');

           j = document.createElement('script');
           j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
           j.async = true;

           d.appendChild(j);
       })();
    </script>
    <noscript>为正常使用来必力评论功能请激活JavaScript</noscript>
    </div>

</html>
